<?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * this class user to do operations related to user.
 *
 * @author jianfeng
 */
class BAPermitCooker extends BAEventCooker {

    const PermitType_rolePermit = 'rolePermit';
    const PermitType_birthPermit = 'birthPermit';
    const PermitType_All = 'allPermit';
    const Effective_Time_Forever = 'effective_forever';
    const Effective_Time_Birth_Offset_10 = 'birth_offset_10';
    const Effective_Time_Birth_Offset_20 = 'birth_offset_20';
    const Effective_Time_Birth_Offset_30 = 'birth_offset_30';

    public function getPermitType($permitType) {
        if (is_numeric($permitType) && $permitType > 0) {
            $id = $permitType;
            $pType = new BACategory($id);
            return $pType;
        }
        if ($permitType instanceof BACategory)
            return $permitType;

        if (is_string($permitType)) {
            if (strpos($permitType, 'permitType') === FALSE) {
                $permitType = 'permitType.' . $permitType;
            }
            $categoryRoot = BACategory::getMyRootNode();
            return $categoryRoot->getChild($permitType);
        }
        return FALSE;
    }

    public function getPermitTypeList($format = 'objectList') {
        $categoryRoot = BACategory::getMyRootNode();
        $permitTypeRoot = $categoryRoot->getChild('permitType');
        $permitTypeList = array();
        if ($permitTypeRoot instanceof BACategory) {
            $permitTypeList = $permitTypeRoot->getChildrenAsLeaf();
            if ($format = 'aliasList') {
                $aliasList = array();
                foreach ($permitTypeList as $name => $value) {
                    $aliasList[$name] = $value;
                }
                return $aliasList;
            }
        }
        return $permitTypeList;
    }

    public function setCurrentPermitType($permitType) {
        $permitType = $this->getPermitType($permitType);
        if ($permitType != NULL) {
            $id = $permitType->getId();
            Blyn::app()->getActiveOperation()->addContextVariable('permitTypeId', $id);
            return $id;
        }
        return NULL;
    }

    public function getCurrentPermitType($data = NULL) {
        $permitTypeId = Blyn::app()->getActiveOperation()->getContextVariable('permitTypeId');
        if ($permitTypeId != NULL) {
            return $this->getPermitType($permitTypeId);
        }
        return $permitTypeId;
    }

    public function addPermitType($permitTypeName, $alias = NULL) {

        if ($alias == NULL) {
            $alias = $permitTypeName;
        }

        if (strpos($permitTypeName, 'permitType') === FALSE) {
            $permitTypeName = 'permitType.' . $permitTypeName;
        } else {
            $permitTypeName = $permitTypeName;
        }
        $categoryRoot = BACategory::getMyRootNode();
        return $categoryRoot->addChild(array('name' => $permitTypeName, 'value' => $alias));
    }

    public function addPermitTypeToPermit($permitTypeData, $permitData) {

        $permitType = $this->getPermitType($permitTypeData);

        $permit = $this->getPermit($permitData);

        if ($permitType != NULL && $permit != NULL) {
            $permit->addItem('permitTypeId', $permitType->getId());
            return $permit;
        }

        return FALSE;
    }

    public function getPermitTypeByPermit($permit) {
        if ($permit != NULL) {
            $permit = $this->getPermit($permit);

            if ($permit->getItem('permitTypeId') != NULL) {
                $typeId = $permit->getItem('permitTypeId')->getValue();
                return $this->getPermitType($typeId);
            }
        }
        return FALSE;
    }

    public function isMemberOfPermitType($permit, $permitType, $recursive = FALSE) {

        $aPermitType = $this->getPermitType($permitType);

        $permitType = $this->getPermitTypeByPermit($permit);

        if ($aPermitType != NULL && $permitType != NULL) {
            if ($aPermitType->getId() == $permitType->getId()) {
                return TRUE;
            }

            if ($recursive) {
                if ($permitType->isChildOf($aPermitType, $recursive)) {
                    return TRUE;
                }
            }
        }
        return FALSE;
    }

    public function addPermit($permitData = null, $permit = 'allow', $expireTime = 'no-expire') {

        if (!is_array($permitData))
            $permitData = array();

        if ($expireTime == NULL || $expireTime == 'no-expire') {
            $expireTime = 9999999999; //means never expire
        }

        if ($permit == NULL) {
            $permit == 'allow';
        }

        if (!isset($permitData['expireTime']))
            $permitData['expireTime'] = $expireTime;
        if (!isset($permitData['permit']))
            $permitData['permit'] = $permit;

        $permitData['lastChangeTime'] = time();

        $itemData = array();

        $permitTable = new BASheet('permit');
        $list = $permitTable->getList(array('itemData' => $permitData));

        if ($list == NULL) {
            $permitTable->addList($permitData);
        }

        return $list;
    }

    /**
     * if find permit, return true, otherwise return false
     */
    public function checkPermit($permitData, $permit = 'allow') {

        $itemContext = array();

        $permitable = new BASheet('permit');
        if (is_array($permitData) && !isset($permitData['permit'])) {
            $permitData['permit'] = $permit;
        }
        $permit = $permitable->getList(array('itemData' => $permitData));

        if ($permit != NULL) {
            if ($permit->getItem('expireTime') != NULL) {
                if ($permit->getItem('expireTime')->getValue() <= time()) {
                    $permitable->deleteList($permit->getId()); //delete it if expired
                    return FALSE;
                }
            }

            //if find permit, return true
            return TRUE;
            /*
              if ($permit->getItem('permit') != NULL) {
              if (strtolower($permit->getItem('permit')->getValue()) == 'allow')
              return $permit->getItem('permit')->getValue();
              }
             * 
             */
        }

        //by default, return false
        return FALSE;
    }

    public function getPermit($permitData, $format = 'string') {
        $itemContext = array();
        $permit = NULL;

        $permitable = new BASheet('permit');

        if (is_numeric($permitData) && $permitData > 0) {
            $permit = $permitable->getListById($permitData);
            $format = 'treeList';
        }

        if ($permitData instanceof BTreeList) {
            $permit = $permitData;
            $format = 'treeList';
        }

        if ($permit == NULL)
            $permit = $permitable->getList(array('itemData' => $permitData));

        if ($permit != NULL) {
            if ($permit->getItem('expireTime') != NULL) {
                if ($permit->getItem('expireTime')->getValue() <= time()) {
                    $permitable->deleteList($permit->getId()); //delete it if expired
                    return FALSE;
                }
            }

            if ($format == 'string') {
                if ($permit->getItem('permit') != NULL) {
                    return $permit->getItem('permit')->getValue();
                }
            } else {
                return $permit;
            }
        }

        //by default, return false
        return FALSE;
    }

    public function getCurrentPermit() {
        $permitId = $this->activeLink->getLinkVariable('permitId');
        if ($permitId != NULL) {
            Blyn::app()->getActiveOperation()->addContextVariable('permitId', $permitId);
        } else {
            $permitId = Blyn::app()->getActiveOperation()->getContextVariable('permitId');
        }
        return $this->getPermit($permitId);
    }

    public function getPermitList($permitData) {

        $permitable = new BASheet('permit');

        $permitView = $permitable->getView(array('itemData' => $permitData));
        $permitList = array();

        //delete expire permit
        foreach ($permitView as $id => $permit) {
            if ($permit != NULL) {
                if ($permit->getItem('expireTime') != NULL) {
                    if ($permit->getItem('expireTime')->getValue() <= time()) {
                        $permitable->deleteList($permit->getId()); //delete it if expired
                    }
                }

                if ($permit->getItem('permit') != NULL) {
                    $permitList[$id] = $permit;
                }
            }
        }

        //by default, return false
        return $permitList;
    }

    /**
     * this function return all permit which's role contain user
     * @param type $permitData
     */
    public function getUserPermitList($permitData, $user = NULL) {

        /**
          $space = Blyn::app()->getActiveSpace();
          $user = Blyn::app()->getCurrentUser();
          $lastPermitChangeTime = $space->getAttribute('lastMemberCardPermitChangeTime');
          $userChangeTime = $user->getAttribute('lastMemberCardPermitChangeTime');

          if ($lastPermitChangeTime != $userChangeTime) {
          $user->addAttribute('lastMemberCardPermitChangeTime', $lastPermitChangeTime);
          }

          $dependency = new CExpressionDependency($lastPermitChangeTime == $userChangeTime);

          $jsonPermit = json_encode($permitData);
          $mdPermit = md5($jsonPermit);

          $rPermitList = Blyn::app()->getCurrentUser()->getCache($mdPermit);

          if ($rPermitList == NULL) {
         * 
         */
        $permitList = $this->getPermitList($permitData);

        $userCooker = new BAUserCooker();

        $user = $userCooker->getUserByInfo($user);

        $pList = array();

        if ($permitList != NULL) {

            if ($user instanceof BUser) {
                //$userRoles = BRole::findUserRoles($user, NULL, TRUE);
            }

            $isAllowApply = FALSE;
            foreach ($permitList as $id => $permit) {
                $isAllowApply = $this->checkPermitByRole($permit, $user);
                if ($this->isMemberOfPermitType($permit, self::PermitType_birthPermit)) {
                    $isAllowApply = $this->isBirthPermitValid($permit);
                }
                if ($isAllowApply) {
                    $pList[$id] = $permit;
                }
            }
        }

        return $pList;
        //$user->setCache($mdPermit, $value, 0, $dependency);
        //}
    }

    /**
     * 如果有效，返回过期的时间
     * @param type $permit
     * @param type $userData
     * @return mix, if valid, return 
     */
    public function isBirthPermitValid($permit, $userData = NULL) {

        $userCooker = new BAUserCooker();
        $oUserInfo = $userCooker->getUserInfo($userData);
        if ($oUserInfo->getItem('birth') != NULL) {
            $birth = $oUserInfo->getItem('birth')->getValue();
        }

        if (isset($birth) && $birth != NULL) {
            //默认检查生日前后15天
            $birthAdvance = '15 days';
            $birthExtend = '15 days';

            if ($permit->getItem('birthTimeSpan') != NULL && $permit->getItem('timeUnit') != NULL) {
                $timeUnit = $permit->getItem('timeUnit')->getValue();
                $timeSpan = $permit->getItem('birthTimeSpan')->getValue();
                if ($timeSpan > 1) {
                    $timeUnit .= 's';
                }
                $birthAdvance = $timeSpan . ' ' . $timeUnit;
                $birthExtend = $timeSpan . ' ' . $timeUnit;
            }

            $tBirth = strtotime($birth);
            if (is_numeric($tBirth) && $tBirth != NULL) {
                $dtBirth = new DateTime($birth);
                $birthYear = date('Y', $tBirth);
                $thisYear = date('Y');
                $interval = $thisYear - $birthYear;
                if ($interval > 1) {
                    $interval .= ' years';
                } else {
                    $interval.= ' year';
                }
                //获得当前年份的生日
                //$tThisYearBirth = strtotime($birth, '+' . $interval);
                $thisYearBirth = $dtBirth->modify('+' . $interval);
                $dtBirth->getTimestamp();
                //$lastMonthDayOfThisYearBirth = date('Y-m-t', $thisYearBirth);
                //$firstMonthDayOfThisYearBirth = $thisYearBirth->modify('first day of this month');
                //生日减去提前天数
                $startTime = 0;
                $endTime = 0;
                if (isset($birthAdvance) && $birthAdvance != NULL) {
                    $advancedBirthDay = clone $thisYearBirth;
                    $advancedBirthDay->modify('-' . $birthAdvance);
                    $startTime = $advancedBirthDay->getTimeStamp();
                }
                //生日加上延长天数
                if (isset($birthExtend) && $birthExtend != NULL) {
                    $extendBirthDay = clone $thisYearBirth;
                    $extendBirthDay->modify('+' . $birthExtend);
                    $endTime = $extendBirthDay->getTimeStamp();
                }
                if (time() >= $startTime && time() <= $endTime) {
                    return $endTime;
                }
            }
        }

        return FALSE;
    }

    public function getPermitExpireTime($permit, $userData = NULL) {

        $permit = $this->getPermit($permit);

        if ($this->isMemberOfPermitType($permit, self::PermitType_birthPermit)) {
            return $this->isBirthPermitValid($permit, $userData);
        }
    }

    protected function checkPermitByRole($permit, $user) {
        $roleId = $permit->getItem('roleId')->getValue();
        $role = new BRole($roleId);
        if ($user->isMemberOfRole($role)) {
            return TRUE;
        }
        return FALSE;
    }

    /**
     * 通过用户的生日和机构设置的提前天数检查是否合格
     * 这个函数会首先计算出生日月份， 然后从生日月份的第一天计算提前天数
     * 从计算的提前天数开始，到生日月份结束
     * @param type $permit
     * @param type $birth
     * @return boolean
     */
    /*
      protected function checkPermitByBirth($permit, $birth = NULL) {

      if ($birth == NULL) {
      $userCooker = new BAUserCooker();
      $oUserInfo = $userCooker->getUserInfo();
      if ($oUserInfo->getItem('birth') != NULL) {
      $birth = $oUserInfo->getItem('birth')->getValue();
      }
      }
      if ($birth != NULL) {
      //默认检查生日前后15天
      $birthAdvance = '15 days';
      $birthExtend = '15 days';

      if ($permit->getItem('birthTimeSpan') != NULL && $permit->getItem('timeUnit') != NULL) {
      $timeUnit = $permit->getItem('timeUnit');
      $timeSpan = $permit->getItem('birthTimeSpan');
      if ($timeSpan > 1) {
      $timeUnit .= 's';
      }
      $birthAdvance = $timeSpan . ' ' . $timeUnit;
      $birthExtend = $timeSpan . ' ' . $timeUnit;
      }

      $tBirth = strtotime($birth);
      if (is_numeric($tBirth) && $tBirth != NULL) {
      $dtBirth = new DateTime($birth);
      $birthYear = date('Y', $tBirth);
      $thisYear = date('Y');
      $interval = $thisYear - $birthYear;
      if ($interval > 1) {
      $interval .= ' years';
      } else {
      $interval.= ' year';
      }
      //获得当前年份的生日
      //$tThisYearBirth = strtotime($birth, '+' . $interval);
      $thisYearBirth = $dtBirth->modify('+' . $interval);
      $dtBirth->getTimestamp();
      //$lastMonthDayOfThisYearBirth = date('Y-m-t', $thisYearBirth);
      //$firstMonthDayOfThisYearBirth = $thisYearBirth->modify('first day of this month');
      //生日减去提前天数
      $startTime = 0;
      $endTime = 0;
      if (isset($birthAdvance) && $birthAdvance != NULL) {
      $advancedBirthDay = $thisYearBirth->modify('-' . $birthAdvance);
      $startTime = $advancedBirthDay->getTimeStamp();
      }
      //生日加上延长天数
      if (isset($birthExtend) && $birthExtend != NULL) {
      $extendBirthDay = $thisYearBirth->modify('+' . $birthExtend);
      $endTime = $extendBirthDay->getTimeStamp();
      }
      if (time() >= $startTime && time() <= $endTime) {
      return TRUE;
      }
      }
      }

      return FALSE;
      }
     * 
     */

    public function getPermitRoleIdList($permitData) {

        $permitList = array();

        $permitable = new BASheet('permit');

        $roleIdList = $permitable->getValueList('roleId', array('itemData' => $permitData));

        return $roleIdList;
    }

    /**
     * 这个函数获取机构所有会员的生日许可，根据这个许可，机构可以进行主动推送
     * 消费券等行为
     */
    public function getAllActiveBirthPermit($permitData) {

        $permitList = $permitTable = $this->getPermitList($permitData);
        $userCooker = new BAUserCooker();

        $retPermitList = array();

        foreach ($permitList as $id => $permit) {
            if ($this->isMemberOfPermitType($permit, self::PermitType_birthPermit)) {
                $birthTimeSpan = 15;
                $birthTimeSpanItem = $permit->getItem('birthTimeSpan');
                if ($birthTimeSpanItem != NULL) {
                    $birthTimeSpan = $birthTimeSpanItem->getValue();
                }
                $timeUnit = $permit->getItem('timeUnit')->getValue();
                if ($birthTimeSpan > 1) {
                    $timeUnit .= 's';
                }
                $users = $userCooker->getAllUsersWithinBirthSpan($birthTimeSpan . ' ' . $timeUnit);
                foreach ($users as $uId => $userInfo) {
                    $userIdItem = $userInfo->getItem('userId');
                    if ($userIdItem != NULL) {
                        //$isAllowApply = $this->checkPermitByRole($permit, $userInfo);
                        $userId = $userIdItem->getValue();
                        if (is_numeric($userId) && $userId > 0) {
                            $user = new BUser($userId);
                            if ($this->checkPermitByRole($permit, $user)) {
                                array_push($retPermitList, array('userInfo' => $userInfo, 'permit' => $permit));
                            }
                        }
                    }
                }
            }
        }

        return $retPermitList;
    }

}
